package com.lipaluma.csv.config;

import com.lipaluma.config.Configuration;
import com.lipaluma.csv.annotations.config.CSV;
import com.lipaluma.csv.io.CsvSourceFactory;
import com.lipaluma.csv.xml.configuration.XmlCsvConfiguration;
import com.lipaluma.io.SourceFactory;

public class CsvConfiguration implements Configuration {
	private int headerLine;
	private boolean mapColumnsByHeaders;
	private int nbLinesHeader;
	private boolean hasHeader;
	private boolean writeHeader;
	
	private boolean trimAll;
	private char quote;
	private char delimiter;
	
	public CsvConfiguration() {
		nbLinesHeader = 1;
		headerLine = 1;
		mapColumnsByHeaders = false;
		hasHeader = false;
		writeHeader = false;
		trimAll = false;
		quote = CsvSourceFactory.CSV_DEFAULT_QUOTE;
		delimiter = CsvSourceFactory.CSV_DEFAULT_DELIMITER;
	}

	public CsvConfiguration(CSV csv) {
		mapColumnsByHeaders = csv.mapColumnsByHeaders();
		nbLinesHeader = csv.nbLinesHeader();
		headerLine = csv.headerLine();
		hasHeader = csv.hasHeader();
		writeHeader = csv.writeHeader();
		delimiter = csv.delimiter();
		quote = csv.quote();
		trimAll = csv.trimAll();
	}

	public CsvConfiguration(XmlCsvConfiguration configuration) {
		mapColumnsByHeaders = configuration.mapColumnsByHeaders();
		nbLinesHeader = configuration.getNbLinesHeader();
		headerLine = configuration.getHeaderLine();
		hasHeader = configuration.hasHeader();
		writeHeader = configuration.writeHeader();
		delimiter = configuration.getDelimiter();
		quote = configuration.enclosedBy();
		trimAll = configuration.isAllTrimed();
	}

	private CsvConfiguration(Builder builder) {
		mapColumnsByHeaders = builder.mapColumnsByHeaders;
		nbLinesHeader = builder.nbLinesHeader;
		headerLine = builder.headerLine;
		hasHeader = builder.hasHeader;
		writeHeader = builder.writeHeader;
		delimiter = builder.delimiter;
		quote = builder.quote;
		trimAll = builder.trimAll;
	}

	public int getHeaderLine() {
		return headerLine;
	}
	
	public boolean isColumnsMappedByHeaders() {
		return mapColumnsByHeaders;
	}
	
	public int getLinesHeaderNumber() {
		return nbLinesHeader;
	}
	
	public boolean hasHeader() {
		return hasHeader;
	}

	public boolean writeHeader() {
		return writeHeader;
	}
	
	public char getDelimiter() {
		return delimiter;
	}
	
	public char getQuote() {
		return quote;
	}
	
	public boolean isAllValuesTrimed() {
		return trimAll;
	}
	
	@Override
	public SourceFactory createSourceFactory() {
		return new CsvSourceFactory(delimiter, quote, trimAll);
	}
	
	public static Builder builder() {
		return new Builder();
	}
	
	public static class Builder {
		private int nbLinesHeader = 1;
		private int headerLine = 1;
		private boolean mapColumnsByHeaders = false;
		private boolean hasHeader = false;
		private boolean writeHeader = false;
		private boolean trimAll = false;
		private char quote = CsvSourceFactory.CSV_DEFAULT_QUOTE;
		private char delimiter = CsvSourceFactory.CSV_DEFAULT_DELIMITER;

		public Builder withHeadersNameLineAt(int headerLine) {
			this.headerLine = headerLine;
			return this;
		}
		public Builder hasHeader() {
			this.hasHeader = true;
			return this;
		}
		public Builder writeHeader() {
			this.writeHeader = true;
			return this;
		}
		public Builder withNumberLinesOfHeader(int nbLines) {
			this.nbLinesHeader = nbLines;
			return this;
		}
		public Builder mapColumnsByHeadersName() {
			this.mapColumnsByHeaders = true;
			return this;
		}
		public Builder trimAllValues(){
			this.trimAll=true;
			return this;
		}
		public Builder withQuoteCharacter(char quote){
			this.quote=quote;
			return this;
		}
		public Builder withDelimiter(char delimiter){
			this.delimiter=delimiter;
			return this;
		}
		public CsvConfiguration build(){
			return new CsvConfiguration(this);
		}
	}
}
